/*
    The NeonX Library

    Copyright (c) 2013 darkcat

    Code covered by the MIT License
*/

#pragma once

// NX_...
#include "macro/macro.h"

//////////////////////////////////////////////////////////////////////////

/*
    Iterative content
*/

#define NX_PP_ITERA_1_E(args, i, nul)   NX_JOIN(NX_ARGS_F1(args), i) nul
#define NX_PP_ITERA_1_F(args, i, nxt)   NX_JOIN(NX_ARGS_F1(args), i) NX_ARGS_L1(args) nxt
#define NX_PP_ITERA_1(n, con, nul, ...) \
    NX_LOOP(n, NX_PP_ITERA_1_F, NX_ARGS_, NX_PP_ITERA_1_E, nul, con, __VA_ARGS__)

#define NX_PP_ITERA_2_E(args, i, nul)   NX_JOIN(NX_ARGS_F1(args), i) NX_JOIN(NX_ARGS_F2(args), i) nul
#define NX_PP_ITERA_2_F(args, i, nxt)   NX_JOIN(NX_ARGS_F1(args), i) NX_JOIN(NX_ARGS_F2(args), i) NX_ARGS_L2(args) nxt
#define NX_PP_ITERA_2(n, con1, con2, nul, ...) \
    NX_LOOP(n, NX_PP_ITERA_2_F, NX_ARGS_, NX_PP_ITERA_2_E, nul, con1, con2, __VA_ARGS__)

#define NX_PP_ITERA_ARGS_E(a, i, nul)   NX_ARGS_F2(a) NX_JOIN(NX_ARGS_F1(a), i)
#define NX_PP_ITERA_ARGS_F(a, i, nxt)   NX_ARGS_F2(a) NX_JOIN(NX_ARGS_F1(a), i), nxt
#define NX_PP_ITERA_ARGS_I(a)           NX_ARGS_F1(a),NX_ARGS_L2(a)
#define NX_PP_ITERA_ARGS(suf, ...) \
    NX_LOOP(NX_CONTER(__VA_ARGS__), NX_PP_ITERA_ARGS_F, NX_PP_ITERA_ARGS_I, NX_PP_ITERA_ARGS_E, , suf, __VA_ARGS__)

/*
    T1 , T2 , T3
*/

#define NX_PP_TYPE(i, T, ...)           NX_PP_ITERA_1(i, T, __VA_ARGS__, __VA_ARGS__,)
#define NX_PP_TYPE_MAX(T, ...)          NX_PP_TYPE(NX_MACRO_MAX, T, __VA_ARGS__)

/*
    P1 * par1 = NULL, P2 * par2 = NULL, P3 * par3 = NULL
*/

#define NX_PP_PARAM(i, P, par, ...)     NX_PP_ITERA_2(i, P, par, __VA_ARGS__, __VA_ARGS__,)
#define NX_PP_PARAM_MAX(P, par, ...)    NX_PP_PARAM(NX_MACRO_MAX, P, par, __VA_ARGS__)

/*
    void, void, void, void, void
*/

#define NX_PP_REPEAT(i, con)            NX_CLONE(i, con, ,)
#define NX_PP_REPEAT_MAX(con)           NX_PP_REPEAT(NX_PP_MAX, con)

/*
    NX_MULTIPLE, NX_MULTIPLE_MAX
*/

#include "macro/multiple.h"

#define NX_PP_MUL                       NX_MULTIPLE
#define NX_PP_MAX                       NX_MULTIPLE_MAX
#define NX_PP_REM(num)                  NX_SUB(NX_MACRO_MAX, num)
